﻿/*
Copyright (c) 2010 Lance Ward
This software is licensed under the MIT license, except where otherwise noted.
For complete license details, refer to license.txt
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace ADNLib
{
	
	public enum ColorType
	{
		PathGradient,
		LinearGradient,
		Solid,
		Unspecified
	}

    [Serializable]
	public class XColor
	{
		private ColorType _type = ColorType.Unspecified;
		private List<ARGB> _colors = new List<ARGB>();
		private float _angle = 0.0f;

		public XColor(ColorType type, Color color)
		{
			_type = type;
			_colors.Add(new ARGB(color));
		}

		public XColor()
		{ }

		public XColor Clone()
		{
			XColor clone = new XColor();
			clone.Type = this._type;
			clone.Angle = this._angle;

			for (int i = 0; i < _colors.Count; i++)
			{
				clone.Colors.Add(_colors[i].Clone());
			}

			return clone;
		}

		[XmlAttribute("TYPE")]
		public ColorType Type
		{
			get
			{
				return _type;
			}
			set
			{
				_type = value;
			}
		}

		[XmlElement("COLOR")]
		public List<ARGB> Colors
		{
			get
			{
				return _colors;
			}
			set
			{
				_colors = value;
			}
		}

		[XmlAttribute("ANGLE")]
		public float Angle
		{
			get
			{
				return _angle;
			}
			set
			{
				_angle = value;
			}
		}

		public ColorBlend GetColors()
		{
			ColorBlend blend = new ColorBlend();
			float[] positions = new float[_colors.Count];
			Color[] blendColors = new Color[_colors.Count];

			for (int i = 0; i < _colors.Count; i++)
			{
				positions[i] = _colors[i].Stop;
				blendColors[i] = _colors[i].GetColor();
			}

			blend.Positions = positions;
			blend.Colors = blendColors;

			return blend;
		}

		public void SetColors(ColorBlend blend)
		{
			if (blend == null) { return; }
			_colors.Clear();
			for (int i = 0; i < blend.Colors.Length; i++)
			{
				ARGB argb = new ARGB(blend.Colors[i]);
				argb.Stop = blend.Positions[i];
				_colors.Add(argb);
			}
		}

		public Brush GetBrush(RectangleF bounds)
		{
			Brush b = null;

			switch (_type)
			{
				case ColorType.LinearGradient:
                    ColorBlend blend = GetColors();
					if (bounds.Height == 0 || bounds.Width == 0) { bounds.Height++; bounds.Width++; }
					LinearGradientBrush lgb = new LinearGradientBrush(bounds, Color.Transparent, Color.Transparent, _angle);
					lgb.InterpolationColors = blend;
					b = lgb;
					break;
				case ColorType.PathGradient:
					GraphicsPath path = new GraphicsPath();
					PathGradientBrush pgb = new PathGradientBrush(path);
					pgb.SurroundColors = new Color[3] { Color.Black, Color.Blue, Color.Red };
					pgb.CenterColor = Color.Red;
					//pgb.CenterPoint = .5f;
					
					break;
				case ColorType.Solid:
					b = new SolidBrush(_colors[0].GetColor());
					break;
				case ColorType.Unspecified:
					b = new SolidBrush(Color.Gray);	//default
					break;
			}

			return b;
		}

		public Pen GetPen(RectangleF bounds, float lineWidth)
		{
			Pen p = new Pen(Color.Black);

			switch (_type)
			{
				case ColorType.LinearGradient:
					p = new Pen(this.GetBrush(bounds), lineWidth);
					break;
				case ColorType.PathGradient:
					break;
				case ColorType.Solid:
					p = new Pen(_colors[0].GetColor(), lineWidth);
					break;
				case ColorType.Unspecified:
					p = new Pen(Color.Black, lineWidth);	//default
					break;
			}

			return p;
		}
	}

    [Serializable]
	public class ARGB
	{
		private int a = 0;
		private int r = 0;
		private int g = 0;
		private int b = 0;
		private float stop = 0.0f;

		public ARGB()
		{

		}

		public ARGB(Color color)
		{
			a = color.A;
			r = color.R;
			g = color.G;
			b = color.B;
		}

		public ARGB(int a, int r, int g, int b)
		{
			this.a = a;
			this.r = r;
			this.g = g;
			this.b = b;
		}

		public Color GetColor()
		{
			return Color.FromArgb(a, r, g, b);
		}

		public ARGB Clone()
		{
			ARGB clone = new ARGB();
			clone.A = this.a;
			clone.R = this.r;
			clone.G = this.g;
			clone.B = this.b;
			clone.Stop = this.stop;

			return clone;
		}

		[XmlAttribute]
		public int A
		{
			get
			{
				return a;
			}
			set
			{
				a = value;
			}
		}

		[XmlAttribute]
		public int R
		{
			get
			{
				return r;
			}
			set
			{
				r = value;
			}
		}

		[XmlAttribute]
		public int G
		{
			get
			{
				return g;
			}
			set
			{
				g = value;
			}
		}

		[XmlAttribute]
		public int B
		{
			get
			{
				return b;
			}
			set
			{
				b = value;
			}
		}

		[XmlAttribute]
		public float Stop
		{
			get
			{
				return stop;
			}
			set
			{
				stop = value;
			}
		}
	}
}
